#include "cmdTask.h"
#include "transFile.h"

void user_init(user_t* usr){
    _dirStack_init(&usr->_dirStack);
    usr->_clientFd = -1;
}

void _task_init(task_t* task){
    task = (task_t*)malloc(sizeof(task_t));
    bzero(task, sizeof(task_t));
    task->_cmdType = CMD_TYPE_INIT;
    task->_user = NULL;
}

void doTask(task_t * ptask, _dirStack_t* dirStack)
{
    CmdType taskType = ptask->_cmdType;
    int netfd = ptask->_clientFd;
    switch (taskType) {
    case CMD_TYPE_CD:
        cmdCd(ptask, dirStack); // 传递 netfd 以便与客户端通信
        break;
    case CMD_TYPE_LS:
        cmdLs(ptask, dirStack);
        break;
    case CMD_TYPE_PWD:
        cmdPwd(ptask, dirStack);
        break;
    case CMD_TYPE_MKDIR:
        cmdMkdir(ptask, dirStack);
        break;
    case CMD_TYPE_RMDIR:
        cmdRmdir(ptask, dirStack);
        break;
    case CMD_TYPE_REMOVE:
        cmdRm(ptask, dirStack);
        break;
    case CMD_TYPE_PUTS:
        cmdPuts(ptask, dirStack); // 需实现文件上传逻辑
        break;
    case CMD_TYPE_GETS:
        cmdGets(ptask, dirStack); // 需实现文件下载逻辑
        break;
    default:
        printf("Invalid Cmd\n"); // 修正拼写错误
        send(netfd, "ERROR: Invalid Command", 21, 0); // 通知客户端
        break;
    }
}

/*
 * 建立目录栈
 * 返回值为真：路径正确；假，路径错误
 * 用于获得当前的虚假工作路径、绝对工作路径
 *
 */

bool _get_dirStack(task_t* ptask, // 任务结构体
                   _dirStack_t* dirstack, // 目录栈地址
                   char* absDir[], // 绝对目录地址
                   char* fakeDir[] // 相对目录地址
                   ){
    /* const char root[] = "/home/ming/ming-space/cloud_T1";//TODO 修改ming为用户名 */
    const char root[] = "/home/ming/ming-space/cloud_T1/";//TODO 修改ming为用户名
    /* printf("curstack = %s\n", _dirStack_getDir(dirstack)); */
    char* cmdPath = strdup(ptask->_data);
    if(cmdPath == NULL){
        fprintf(stderr, "empty path.\n");
        return false;
    }
    /* printf("cmdPath = %s\n", cmdPath); */
    char curpath[4096] = { 0 };
    char* token = strtok(cmdPath, "/");


    while(token){
        /* printf("token = %s\n", token);// test */
        if(strcmp(token, ".") == 0){
            token = strtok(NULL, "/");
            /* printf("curstack = %s\n", _dirStack_getDir(dirstack)); */
            continue;
        }
        else if(strcmp(token, "..") == 0){
            if(_dirStack_pop(dirstack) == 1){
                /* popFlag = true; */
                return false;
            }
        }
        else if(token){
            _dirStack_push(dirstack, token);
        }
        else{
            break;
        }

        /* printf("curstack = %s\n", _dirStack_getDir(dirstack)); */
        token = strtok(NULL, "/");
    }

    strcpy(curpath, root);
    snprintf(curpath, sizeof(curpath), "%s%s", root, _dirStack_getDir(dirstack));
    curpath[strlen(curpath) - 1] = '\0'; // 仅当末尾有斜杠时处理
    /* strcat(curpath, _dirStack_getDir(dirstack)); */
    /* curpath[strlen(curpath) - 1] = '\0'; */
    /* printf("curpath = %s\n", curpath); */
    
    char absstr[4096] = { 0 };
    strcat(absstr, root);
    strcat(absstr, curpath + strlen(root));
    /* printf("absolute path = %s\n", absstr); */
    /* printf("cd token = %s\n", token); */

    char fakerRoot[4096] = { 0 };
    strcat(fakerRoot, "~/ming-space/cloud_T1/");// TODO 修改为用户名
    strcat(fakerRoot, curpath + strlen(root));
    /* printf("fakeRoot = %s\n", fakerRoot); */

    //*absDir = (char*)calloc(strlen(absstr), sizeof(char));
    //*fakeDir = (char*)calloc(strlen(fakerRoot), sizeof(char));
    *absDir = strdup(absstr);
    *fakeDir = strdup(fakerRoot);

    /* printf("_get_dirStack end\n"); */

    return true;
}


bool _dirAccess(task_t *ptask, _dirStack_t* dirStack){
    char curDir[4096] = { 0 };
    getcwd(curDir, sizeof(curDir));
    strcat(curDir, "/");
    /* printf("curDir() = %s\n", curDir); */
    strcat(curDir, _dirStack_getDir(dirStack));
    /* printf("curDir() = %s\n", curDir); */
    strcat(curDir, ptask->_data);
    /* printf("curDir() = %s\n", curDir); */
    curDir[strlen(curDir) - 1] = '\0';
    if(access(curDir, F_OK) != 0){
        //fprintf(stderr, "_dirAccess FAILED : directory.\n");
        perror("access");
        //free(cmdPath);// TODO
        return false;
    }
    return true;
}

void cmdCd(task_t *ptask, _dirStack_t* dirStack)
{
    printf(">CD-------------------------------------------\n");
    
    printf("curstack = %s\n", _dirStack_getDir(dirStack));
    if(_dirAccess(ptask, dirStack) == false){
        fprintf(stderr, "CD FAILED : access.\n");
        return;
    }

    char* absDir;
    char* fakeDir;
    
    // 临时目录栈 用于在pop错误时恢复原来的目录
    _dirStack_t tmpStack;
    _dirStack_init(&tmpStack);
    _dirStack_copy(&tmpStack, dirStack);

    /* printf("curstack = %s\n", _dirStack_getDir(dirStack)); */

    if(_get_dirStack(ptask, dirStack, &absDir, &fakeDir) == false){
        fprintf(stderr, "CD FAILED : no access right.\n");
        _dirStack_copy(dirStack, &tmpStack);
        /* printf("curstack = %s\n", _dirStack_getDir(dirStack)); */
        /* printf("tmpstack = %s\n", _dirStack_getDir(&tmpStack)); */
        return;
    } 
    /* printf("curFakeDir(after cd) = %s\n", fakeDir); */
    printf("curAbsDir(after cd) = %s\n", absDir);
    
    send(ptask->_user->_clientFd, fakeDir, sizeof(fakeDir), MSG_NOSIGNAL);

    /* printf("curstack = %s\n", _dirStack_getDir(dirStack)); */
    // 如果获取目录成功，则继续处理
    printf("CD SUCCESS!\n");
}


void cmdLs(task_t * ptask, _dirStack_t* dirStack)
{
    printf(">LS-------------------------------------------\n");
    char* absDir;
    char* fakeDir;
    if(_dirAccess(ptask, dirStack) == false){
        fprintf(stderr, "LS FAILED : access.\n");
        return;
    }

    _dirStack_t tmpStack;
    _dirStack_init(&tmpStack);
    _dirStack_copy(&tmpStack, dirStack);
    if(_get_dirStack(ptask, dirStack, &absDir, &fakeDir) == false){
        fprintf(stderr, "LS FAILED : cant open dir.\n");
        return;
    }
    _dirStack_copy(dirStack, &tmpStack);

    /* printf("absDir = %s\n", absDir); */
    /* printf("fakeDir = %s\n", fakeDir); */
    struct stat st;
    int ret = stat(absDir, &st);
    /* printf("struct stat st.st_mode = %d\n", st.st_mode); */
    if(ret == -1){
        fprintf(stderr, "LS FAILED: stat error : not a directory.\n");
        return;
    }
    DIR* dir = opendir(absDir);
    ERROR_CHECK(dir, NULL, "open dir");
    
    struct dirent* entry;
    int rowLimit = 0;
    while((entry = readdir(dir)) != NULL){

        printf("%s ", entry->d_name);
        send(ptask->_user->_clientFd, entry->d_name, sizeof(entry->d_name), MSG_NOSIGNAL);
        ++rowLimit;
        if(rowLimit >= 8){// 一行限制8个
            rowLimit = 0;
            printf("\n");
            send(ptask->_user->_clientFd, "\n", sizeof(char), MSG_NOSIGNAL);
        }
    }
    printf("\n");

    printf(" LS SUCCESS!\n");
}

/*


*/
void cmdPwd(task_t *ptask, _dirStack_t* dirStack)
{
    printf(">PWD-------------------------------------------\n");
    char curDir[4096] = { 0 };
    getcwd(curDir, sizeof(curDir));
    strcat(curDir, "/");
    /* printf("curDir() = %s\n", curDir); */
    strcat(curDir, _dirStack_getDir(dirStack));
    /* printf("curDir() = %s\n", curDir); */
    strcat(curDir, ptask->_data);
    /* printf("curDir() = %s\n", curDir); */
    curDir[strlen(curDir) - 1] = '\0';
   

    printf("pwd = %s\n", curDir);
    send(ptask->_user->_clientFd, curDir, sizeof(curDir), MSG_NOSIGNAL);
    printf("PWD SUCCESS!\n");
}

/*


*/
void cmdMkdir( task_t * ptask, _dirStack_t* dirStack)
{
    printf(">MKDIR-------------------------------------------\n");
    char* absDir;
    char* fakeDir;
        
    if(_get_dirStack(ptask, dirStack, &absDir, &fakeDir) == false){
        printf("MKDIR FAILED: wrong dirName\n");
        return;
    }
    /* printf("absDir = %s\n", absDir); */
    /* printf("fakeDir = %s\n", fakeDir); */

    if(mkdir(absDir, 0777) != 0){
        fprintf(stderr, "MKDIR FAILED: mkdir.\n");
        return;
    }
    printf("MKDIR SUCCESS!\n");
}

/*


*/
void cmdRmdir(task_t * ptask, _dirStack_t* dirStack)
{
    printf(">RMDIR-------------------------------------------\n");
    char* absDir;
    char* fakeDir;
    if(_get_dirStack(ptask, dirStack, &absDir, &fakeDir) == false){
        printf("RMDIR FAILED: wrong dirName\n");
        return;
    }

    if(rmdir(absDir) != 0){
        fprintf(stderr, "RMDIR FAILED: mkdir.\n");
        return;
    }

    printf("RMDIR SUCCESS!\n");
}

/*


*/
void cmdPuts(task_t * ptask, _dirStack_t* dirStack)
{
    char filename[200] = { 0 };
    memcpy(filename,ptask->_data,sizeof(ptask->_data));

    printf("PUTS SUCCESS!\n");
}
/*


*/
void cmdGets(task_t * ptask, _dirStack_t* dirStack)
{
    printf("GETS SUCCESS!\n");
}
/*


*/
void cmdRm(task_t * ptask, _dirStack_t* dirStack)
{
    printf(">RM-------------------------------------------\n");
      char* absFile;
      char* fakeFile;
      if(_get_dirStack(ptask, dirStack, &absFile, &fakeFile) == false){
          printf("RM FAILED: wrong fileName\n");
          return;
      }

      if(unlink(absFile) != 0){
          fprintf(stderr, "RM FAILED: unlink.\n");
          return;
      }

    printf("RM SUCCESS!\n");
}


// ------------------------------test code----------------------------------------------

/* void runTest(task_t* testTask, CmdType cmdType, const char* testData, void (*cmdFunc)(task_t*, _dirStack_t*), _dirStack_t* dirStack) { */
/*     printf("\n===== Running Test: %s =====\n", testData); */
/*     memset(testTask, 0, sizeof(task_t));  // 重置任务 */
/*     testTask->_cmdType = cmdType; */
/*     testTask->_clientFd = 1;  // 假设客户端的文件描述符为1 */
/*     strcpy(testTask->_data, testData); */
/*     cmdFunc(testTask, dirStack); */
/* } */

/* int main() { */
/*     _dirStack_t dirStack; */
/*     _dirStack_init(&dirStack); */
/*     task_t testTask; */

/*     // **测试 cmdCd** */
/*     /1* runTest(&testTask, CMD_TYPE_CD, "dir1", cmdCd, &dirStack);  // 切换到有效目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_CD, "dir2/../../../", cmdCd, &dirStack);  // 切换到无权限目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_CD, "../dir1/dir2/.././../", cmdCd, &dirStack);  // 切换到有效目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_CD, "../", cmdCd, &dirStack);  // 切换到上级目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_CD, "non_exist_dir", cmdCd, &dirStack);  // 切换到不存在的目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_CD, "/root", cmdCd, &dirStack);  // 切换到无权限目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_CD, "dir1/dir2/dir3/file1", cmdCd, &dirStack);  // 切换到有效目录 *1/ */
    
/*     // **测试 cmdLs** */
/*     /1* runTest(&testTask, CMD_TYPE_LS, "", cmdLs, &dirStack);  // 列出有效目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_LS, "dir1", cmdLs, &dirStack);  // 列出有效目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_LS, "non_exist_dir", cmdLs, &dirStack);  // 列出不存在的目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_LS, "/root", cmdLs, &dirStack);  // 列出无权限目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_LS, "1.txt", cmdLs, &dirStack);  // 列出文件 *1/ */

/*     // **测试 cmdPwd** */
/*     /1* runTest(&testTask, CMD_TYPE_PWD, "", cmdPwd, &dirStack);  // 显示当前目录 *1/ */

/*     // **测试 cmdMkdir** */
/*     /1* runTest(&testTask, CMD_TYPE_MKDIR, "new_dir", cmdMkdir, &dirStack);  // 创建新目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_MKDIR, "existing_dir", cmdMkdir, &dirStack);  // 创建已存在的目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_MKDIR, "/root", cmdMkdir, &dirStack);  // 无权限创建目录 *1/ */

/*     // **测试 cmdRmdir** */
/*     /1* runTest(&testTask, CMD_TYPE_RMDIR, "new_dir", cmdRmdir, &dirStack);  // 删除空目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_RMDIR, "empty_dir", cmdRmdir, &dirStack);  // 删除空目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_RMDIR, "non_empty_dir", cmdRmdir, &dirStack);  // 删除非空目录 *1/ */
/*     /1* runTest(&testTask, CMD_TYPE_RMDIR, "non_exist_dir", cmdRmdir, &dirStack);  // 删除不存在的目录 *1/ */

/*     // **测试 cmdPuts** */
/*     /1* runTest(&testTask, CMD_TYPE_PUTS, "file_to_upload.txt", cmdPuts, &dirStack);  // 上传文件 *1/ */

/*     // **测试 cmdGets** */
/*     /1* runTest(&testTask, CMD_TYPE_GETS, "file_to_download.txt", cmdGets, &dirStack);  // 下载文件 *1/ */

/*     // **测试 cmdRm** */
/*     /1* runTest(&testTask, CMD_TYPE_REMOVE, "1.txt", cmdRm, &dirStack);  // 删除文件 *1/ */

/*     return 0; */
/* } */
